package com.settlement.system.controller;

import com.settlement.system.csv.CsvDatas;
import com.settlement.system.common.enums.ChannelEnum;
import com.settlement.system.common.exception.ServiceException;
import com.settlement.system.model.entity.common.*;
import com.settlement.system.reply.ObjectDataResponse;
import com.settlement.system.service.*;
import com.settlement.system.service.csv.OrderAuditCsvDatas;
import com.settlement.system.service.extend.BatchSave;
import com.settlement.system.common.util.common.FasUtil;
import com.settlement.system.common.util.common.OrderAuditCategoryCalculatorUtils;
import com.settlement.system.common.util.common.RedisUtil;
import com.alibaba.excel.context.AnalysisContext;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 订单稽核报表 前端控制器
 *
 * @author Ximi
 * @since 2020-09-22
 */

@Api(tags = "订单稽核报表", description = "订单稽核报表")
@RestController
@RequestMapping("/order/audit/report")
@Slf4j
public class TblOrderAuditReportController extends ExcelController<TblOrderAuditReport> {

    public static final String BATCH_NUMBER = "acs_order_audit_batch_number";

    @Value("${system.export-root.path}")
    private String exportRootPath;

    @Resource
    private ITblOrderAuditReportService tblOrderAuditReportService;

    @Resource
    private ITblReceiveRefundShopService tblReceiveRefundShopService;

    @Resource
    private ITblReceiveRefundAccountService tblReceiveRefundAccountService;

    @Resource
    private ITblOrderCloseAccountService orderCloseAccountService;

    @Resource
    private ITblOrderAuditCategoryService orderAuditCategoryService;

    @Override
    public IBaseService init() {
        return tblOrderAuditReportService;
    }

    @Override
    public Class<?> getModelClass() {
        return TblOrderAuditReport.class;
    }

    @Override
    @ApiOperation("分页查询")
    @RequestMapping(value = "list", method = {RequestMethod.POST})
    @ResponseBody
    protected ObjectDataResponse getPageList(HttpServletRequest request, @RequestBody BasePager<Map<String, Object>> model) {
        Map<String, Object> result = new HashMap<>(16);
        try {
            setParamsModel(model.getModel());
            setTmOrJdFlag(model.getModel());
            List<TblOrderAuditReport> rows = tblOrderAuditReportService.selectByPage(new SinglePage(model), model.getModel(),
                    model.getOrderByField(), model.getOrderBy());
            TblOrderAuditReport foot = tblOrderAuditReportService.getFoot(model.getModel());
            fullAuditCategory(rows,model.getModel());
            result.put("rows", rows);
            if (null != foot) {
                result.put("total", foot.getCountSum());
                result.put("foot", foot);
            } else {
                result.put("total", 0);
                result.put("foot", new TblOrderAuditReport());
            }
        } catch (Exception ex) {
            log.error("获取列表出错", ex);
            return new ObjectDataResponse(500, "获取列表失败，请联系管理员！");
        }
        return new ObjectDataResponse<Map>(result, 200, "获取列表成功");
    }

    @Override
    protected void setParamsModel(Map<String, Object> model) {
        setSpOrderNoParams(model);
        FasUtil.formatInQueryCondition(model, "shopNos","receivableAmountTypes",
                "channelNos","companySubject","thirdOrderNo","refBillNo","threeLevelChannelNos");
        super.setParamsModel(model);
    }

    /**
     * 设置京东天猫标识
     * @param model
     */
    private void setTmOrJdFlag(Map<String, Object> model) {
        String channelNos =  (String)model.get("channelNos");
        boolean flag = StringUtils.isNotBlank(channelNos)
                && (channelNos.contains(ChannelEnum.TM.getNo()) || channelNos.contains(ChannelEnum.JD.getNo()));
        if(flag){
            model.put("tmJdFlag","tmJdFlag");
        }
    }

    /**
     * 设置原始外部订单号
     *
     * @param model
     */
    private void setSpOrderNoParams(Map<String, Object> model) {
        try {
            String thirdOrderNo = model.get("thirdOrderNo") != null ? model.get("thirdOrderNo").toString() : null;
            String refBillNo = model.get("refBillNo") != null ? model.get("refBillNo").toString() : null;

            if (StringUtils.isEmpty(thirdOrderNo) && !StringUtils.isEmpty(refBillNo)) {
                String [] refBillNoStr = StringUtils.split(refBillNo,",");
                thirdOrderNo = tblOrderAuditReportService.getSpOrderNo(refBillNoStr);
                if (!StringUtils.isEmpty(thirdOrderNo)) {
                    model.put("thirdOrderNo", thirdOrderNo);
                }
            }
        } catch (Exception ex) {
            log.error("根据优购单号计算原始外部单号异常", ex);
        }
    }

    @Override
    public String verifyImportObject(TblOrderAuditReport tblOrderAuditReport, AnalysisContext analysisContext) {
        if (tblOrderAuditReport.getBusinessDate() == null) {
            return "业务日期不能为空";
        }

        if (StringUtils.isEmpty(tblOrderAuditReport.getShopNo())
                && StringUtils.isEmpty(tblOrderAuditReport.getShopAccount())) {
            return "店铺编码、店铺账号不能同时空";
        }

        if (tblOrderAuditReport.getReceiveAmount() != null
                && tblOrderAuditReport.getReceiveAmount().compareTo(BigDecimal.ZERO) < 0) {
            return "收款金额需要校验必为正数";
        }

        if (tblOrderAuditReport.getRefundAmount() != null
                && tblOrderAuditReport.getRefundAmount().compareTo(BigDecimal.ZERO) > 0) {
            return "退款金额需要校验必为负数";
        }

        if (tblOrderAuditReport.getDepositRefundAmount() != null
                && tblOrderAuditReport.getDepositRefundAmount().compareTo(BigDecimal.ZERO) > 0) {
            return "保证金退款需要校验必为负数";
        }

        try {

            TblOrderCloseAccount closeAccount = null;
            if (!StringUtils.isEmpty(tblOrderAuditReport.getShopNo())) {
                TblReceiveRefundShop receiveRefundShop = tblReceiveRefundShopService.getByShopNo(tblOrderAuditReport.getShopNo());
                if (receiveRefundShop == null) {
                    return "店铺在店铺设置中不存在";
                }
                tblOrderAuditReport.setCompanySubject(receiveRefundShop.getNcEnterAccountBody());
                tblOrderAuditReport.setChannelNo(receiveRefundShop.getChannelNo());
                tblOrderAuditReport.setChannelName(receiveRefundShop.getChannelName());
                tblOrderAuditReport.setShopName(receiveRefundShop.getShopName());
                tblOrderAuditReport.setThreeLevelChannelNo(receiveRefundShop.getThreeChannelNo());
                tblOrderAuditReport.setThreeLevelChannelName(receiveRefundShop.getThreeChannelName());
                tblOrderAuditReport.setNcShopNo(receiveRefundShop.getNcShopNo());
                tblOrderAuditReport.setNcShopName(receiveRefundShop.getNcShopName());
                closeAccount = orderCloseAccountService.getByThreeChannelNoAndShopAccount(receiveRefundShop.getThreeChannelNo(), null);
            }

            if (!StringUtils.isEmpty(tblOrderAuditReport.getShopAccount()) && StringUtils.isEmpty(tblOrderAuditReport.getShopNo())) {
                TblReceiveRefundAccount refundAccount = tblReceiveRefundAccountService.getOrByShopAccount(tblOrderAuditReport.getShopAccount());
                if (null == refundAccount) {
                    return "店铺账号在账号设置中不存在";
                }
                tblOrderAuditReport.setCompanySubject(refundAccount.getNcEnterAccountBody());
                tblOrderAuditReport.setChannelNo(refundAccount.getChannelNo());
                tblOrderAuditReport.setChannelName(refundAccount.getChannelName());
                tblOrderAuditReport.setNcShopName(refundAccount.getNcShopName());
                tblOrderAuditReport.setNcShopNo(refundAccount.getNcShopNo());
                closeAccount = orderCloseAccountService.getByThreeChannelNoAndShopAccount(null, refundAccount.getShopAccount());
            }

            if (closeAccount == null) {
                return "请先设置关账";
            }

            if (closeAccount.getInitialDate().compareTo(closeAccount.getRealCloseAccountDate()) != 0) {
                return "关账日不等于初始日期,不允许进行初始导入";
            }

            if (tblOrderAuditReport.getBusinessDate().compareTo(closeAccount.getInitialDate()) > 0) {
                return "业务日期不能大于初始日期";
            }

            tblOrderAuditReport.setEffectiveDate(tblOrderAuditReport.getBusinessDate());
            tblOrderAuditReport.setExpiredDate(closeAccount.getInitialDate());

        } catch (Exception ex) {
            log.error("验证订单稽核导入异常", ex);
            return "系统异常";
        }
        return null;
    }

    @Override
    protected void saveData(List<TblOrderAuditReport> datas) throws ServiceException {
        long batchNumber = RedisUtil.incr(BATCH_NUMBER, 1);

        for (TblOrderAuditReport report : datas) {
            report.setTransactionalNo((int) batchNumber);
        }

        BatchSave batchSave = new BatchSave(tblOrderAuditReportService, datas);

        try {
            batchSave.save();

        } catch (Exception ex) {
            tblOrderAuditReportService.deleteByTransactionalNo(batchNumber);
            log.error("save imported OrderAudit exception:", ex);
            throw new ServiceException(batchSave.getErrorMessage(), ex);
        }
    }

    @Override
    protected void setFootModel(Map<String, Object> result, Map<String, Object> model) throws ServiceException {
        List<TblOrderAuditReport> rows = (List<TblOrderAuditReport>) result.get("rows");
        fullAuditCategory(rows, model);
        result.put("foot", tblOrderAuditReportService.getFoot(model));
        super.setFootModel(result, model);
    }

    @Override
    protected List<TblOrderAuditReport> getExportDate(Map<String, Object> params) throws ServiceException {
        List<TblOrderAuditReport> list = super.getExportDate(params);
        fullAuditCategory(list, params);
        return list;
    }

    private void fullAuditCategory(List<TblOrderAuditReport> rows, Map<String, Object> map) throws ServiceException {
        List<TblOrderAuditCategory> auditCategories = orderAuditCategoryService.selectByParam(new HashMap<>(16));
        for (TblOrderAuditReport auditReport : rows) {
            TblOrderAuditCategory category = OrderAuditCategoryCalculatorUtils.selectCategory(auditReport, map, auditCategories);
            if (category != null) {
                auditReport.setOrderAuditMainTypeName(category.getMainCategoryName());
                auditReport.setOrderAuditDtlTypeName(category.getDetailCategoryName());
                auditReport.setIsPush(category.getIsPush());
            }
        }
    }

    @Override
    @PostMapping("import")
    @CacheEvict(cacheNames = {"closeAccountByThreeChannelNoAndShopAccount", "rrOrAccountByLoginAccount", "rrShopByShopNo"},
            allEntries = true, beforeInvocation = true)
    public ObjectDataResponse importFile(MultipartFile file, HttpServletRequest request) {
        return super.importFile(file, request);
    }


   /* @Override
    public void exportExcel(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Map<String, Object> params = buildParam(request);
        setParamsModel(params);
        Object fileName = "RR-订单稽核报表";
        String path = exportRootPath + System.currentTimeMillis() + "/";

        OrderAuditCsvDatas csvDatas = new OrderAuditCsvDatas(tblOrderAuditReportService,
                params, orderCloseAccountService,
                orderAuditCategoryService.selectByParam(new HashMap<>(16)));

        CsvExportUtil.createCsv()
                .headClass(TblOrderAuditReport.class)
                .fileName(fileName.toString())
                .model(CsvExportBuilder.MULTI_ZIP_MODEL)
                .parentPath(path)
                .csvDatas(csvDatas)
                .export(request,response);
    }*/

    /**
     * 看到对 csvDatas的处理不一样，自定义导出时，重写一下对应的方法
     */
    @Override
    protected CsvDatas getCsvDatas(Map<String, Object> params) throws ServiceException {
        OrderAuditCsvDatas csvDatas = new OrderAuditCsvDatas(tblOrderAuditReportService,
                params, orderCloseAccountService,
                orderAuditCategoryService.selectByParam(new HashMap<>(16)));
        return csvDatas;
    }
}

